﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FastPoster.MainForms
{
    #region using
    using DevComponents.DotNetBar;
    using FastPoster.MainClasses;
    using Amib.Threading;
    using System.Threading;
    using FastPoster.DataProviders.BUS;
    using FastPoster.Helpers;
    using FastPoster.DataProviders.DTO;
    using System.Diagnostics;
    using mshtml;
    using System.Threading.Tasks;
    using System.Web;
    #endregion

    public partial class FrmKetQuaDangTin : Office2007Form
    {
        public List<Poster>             LstPoster { get; set; }
        public EventHandler             Handler { get; set; }
        public int                      IDM { get; set; }
        public string                   Subj { get; set; }
        public string                   Mess { get; set; }
        public string                   AnswerVerify { get; set; }
        public FrmXacNhanImageCaptcha   frm;
        private BackgroundWorker        PostingBackgroundWorker;
        private int                     currPoster;
        private delegate void PosterProgressChangedDel(object sender, ProgressChangedArgs obj);

        public FrmKetQuaDangTin()
        {
            InitializeComponent();
        }

        public WebBrowser CtrlWebBrowser = new WebBrowser();

        public void InitForm()
        {
            // Load box list
            LoadData();

            // Init progress bar
            progBarKetQuaDangTin.Minimum = 0;
            progBarKetQuaDangTin.Maximum = LstPoster.Count;
            progBarKetQuaDangTin.Step = 1;

            btnNgungDangTin.Enabled = true;
            currPoster = 0;

            // Init background worker
            InitWorker();
        }

        /// <summary>
        /// Init background worker
        /// </summary>
        private void InitWorker()
        {
            PostingBackgroundWorker = new BackgroundWorker();
            PostingBackgroundWorker.WorkerReportsProgress = true;
            PostingBackgroundWorker.WorkerSupportsCancellation = true;

            PostingBackgroundWorker.DoWork += PostingBackgroundWorker_DoWork;
            PostingBackgroundWorker.ProgressChanged += PostingBackgroundWorker_ProgressChanged;
            PostingBackgroundWorker.RunWorkerCompleted += PostingBackgroundWorker_RunWorkerCompleted;
        }

        /// <summary>
        /// Start posting data to all forums
        /// </summary>
        public void StartPost()
        {
            if (PostingBackgroundWorker.IsBusy)
            {
                PostingBackgroundWorker.CancelAsync();
            }
            else
            {
                progBarKetQuaDangTin.Value = progBarKetQuaDangTin.Minimum;
                PostingBackgroundWorker.RunWorkerAsync();
            }
        }

        /// <summary>
        /// Perform posting data to a forum
        /// </summary>
        /// <param name="poster"></param>
        private void DoPost(Poster poster, int Index)
        {
            try
            {
                if (PostingBackgroundWorker.CancellationPending)
                {
                    return;
                }

                dtgvKetQuaDangTin.Rows[Index].Cells[2].Value = DateTime.Now.ToString("G");
                Task.Factory.StartNew(() => poster.StartPost(Index));
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                {
                    GlobalVariables.Logger.Error("DoPost: failed - error: " + ex.InnerException.Message);
                }
                else
                {
                    GlobalVariables.Logger.Error("DoPost: failed - error: " + ex.Message);
                }
            }
        }

        /// <summary>
        /// This method is execute when accomplish posting data 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnPosterProgressChanged(object sender, EventArgs e)
        {
            var eventType = (ProgressChangedArgs)e;
            if (base.InvokeRequired)
            {
                PosterProgressChangedDel del = new PosterProgressChangedDel(OnPosterProgressChanged);
                base.Invoke(del, new object[] { sender, eventType });
            }
            else
            {
                try
                {
                    Poster poster = (Poster)sender;
                    this.dtgvKetQuaDangTin.Rows[(int)eventType.Index].Cells[3].Value = eventType.ProgressState;
                    if (poster.PostFinish)
                    {
                        if (poster.Completed)
                        {
                            this.dtgvKetQuaDangTin.Rows[(int)eventType.Index].Cells[4].Value = poster.ResponseUrl;

                            var objBus = new BaiVietDaDangBUS(GlobalVariables.g_strPath);
                            var objDto = new BaiVietDaDangDTO
                            {
                                IDBaiVietMau = poster.IDM,
                                IDBox = poster.IDB,
                                URL = poster.ResponseUrl,
                                NgayDang = DateTime.Now
                            };
                            if (objBus.Insert(objDto))
                            {
                                GlobalVariables.Logger.Info("Insert URL: " + poster.ResponseUrl);
                            }

                            // Cap nhat lai danh sach cac bai viet da dang
                            GlobalVariables.LstCacBaiVietDaDang.Add(poster.ResponseUrl);
                        }
                        else
                        {
                            if (poster.VerifyCapcha)
                            {
                                var subStr = string.Empty;
                                var posHumanverify = -1;

                                var idHumanverify = RetrieveIDHumanVerify(poster.StrRespond, ref posHumanverify);
                                var modeVerify = RetrieveVerifyMode(poster.StrRespond, idHumanverify, posHumanverify);

                                if (modeVerify == EnumVerifyMode.QUESTION)
                                {
                                    InsertXacNhanBangCauHoi(this.dtgvKetQuaDangTin.Rows[(int)eventType.Index].Cells[1].Value, idHumanverify, posHumanverify);
                                }
                                else // Image
                                {
                                    InsertXacNhanBangHinhAnh(this.dtgvKetQuaDangTin.Rows[(int)eventType.Index].Cells[1].Value);
                                }
                            }
                        }
                        currPoster++;
                        PostingBackgroundWorker.ReportProgress(currPoster >= LstPoster.Count ? 100 : (int)(currPoster / LstPoster.Count * 100));
                    }
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null)
                    {
                        GlobalVariables.Logger.Error("Error on posting: " + ex.InnerException.Message);
                    }
                    else
                    {
                        GlobalVariables.Logger.Error("Error on posting: " + ex.Message);
                    }
                }
            }
        }

        /// <summary>
        /// This method is executed when RunWorkerAsync is called.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PostingBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            GlobalVariables.Logger.Info("Posting: started");
            try
            {
                for (int i = 0; i < LstPoster.Count; i++)
                {
                    Poster poster = (Poster)dtgvKetQuaDangTin.Rows[i].Cells[1].Value;
                    poster.PostFinish = false;
                    poster.ProgressChanged -= OnRePostingProgressChanged_ByCaptcha;
                    poster.ProgressChanged -= OnRePostingProgressChanged_ByCauHoi;
                    poster.ProgressChanged += OnPosterProgressChanged;

                    DoPost(poster, i);
                    if (i > 0 && i % 4 == 0)
                    {
                        Thread.Sleep(10000);
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                {
                    GlobalVariables.Logger.Error("Posing: failed - error: " + ex.InnerException.Message);
                }
                else
                {
                    GlobalVariables.Logger.Error("Posing: failed - error: " + ex.Message);
                }
            }
        }

        private void PostingBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (!PostingBackgroundWorker.CancellationPending)
            {
                progBarKetQuaDangTin.PerformStep();
            }
        }

        private void PostingBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            btnNgungDangTin.Enabled = false;
        }

        private void OnRePostingProgressChanged_ByCauHoi(object sender, EventArgs e)
        {
            var eventType = (ProgressChangedArgs)e;
            Poster poster = (Poster)sender;
            this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[3].Value = AnswerVerify;
            this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[5].Value = eventType.ProgressState;
            if (poster.Completed)
            {
                this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[6].Value = poster.ResponseUrl;
                var objBus = new BaiVietDaDangBUS(GlobalVariables.g_strPath);
                var objDto = new BaiVietDaDangDTO
                {
                    IDBaiVietMau = poster.IDM,
                    IDBox = poster.IDB,
                    URL = this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[6].Value.ToString(),
                    NgayDang = DateTime.Now
                };
                objBus.Insert(objDto);
                // Cap nhat lai danh sach cac bai viet da dang
                GlobalVariables.LstCacBaiVietDaDang.Add(poster.ResponseUrl);
            }
            else if (poster.VerifyCapcha)
            {
                var posHumanverify = -1;
                var idHumanverify = RetrieveIDHumanVerify(poster.StrRespond, ref posHumanverify);

                this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[2].Value = RetrieveBlockrowCauHoi(poster.StrRespond, idHumanverify, posHumanverify);
                this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[3].Value = string.Empty;
                this.dtgvXacNhanBangCauHoi.Rows[(int)eventType.Index].Cells[5].Value = string.Empty;
                GlobalVariables.DictHtmls[poster.Url] = poster.StrRespond;
            }
        }

        private void OnRePostingProgressChanged_ByCaptcha(object sender, EventArgs e)
        {
            var eventType = (ProgressChangedArgs)e;
            Poster poster = (Poster)sender;
            this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[3].Value = AnswerVerify;
            this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[5].Value = eventType.ProgressState;
            if (poster.Completed)
            {
                this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[6].Value = poster.ResponseUrl;
                var objBus = new BaiVietDaDangBUS(GlobalVariables.g_strPath);
                var objDto = new BaiVietDaDangDTO
                {
                    IDBaiVietMau = poster.IDM,
                    IDBox = poster.IDB,
                    URL = this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[6].Value.ToString(),
                    NgayDang = DateTime.Now
                };
                objBus.Insert(objDto);
                // Cap nhat lai danh sach cac bai viet da dang
                GlobalVariables.LstCacBaiVietDaDang.Add(poster.ResponseUrl);
            }
            else if(poster.VerifyCapcha)
            {
                this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[3].Value = string.Empty;
                this.dtgvXacNhanBangHinhAnh.Rows[(int)eventType.Index].Cells[5].Value = string.Empty;
                GlobalVariables.DictHtmls[poster.Url] = poster.StrRespond;
            }
        }

        /// <summary>
        /// Xac dinh id of tag input humanverify[input]
        /// </summary>
        /// <param name="strResponse"></param>
        /// <returns></returns>
        public string RetrieveIDHumanVerify(string strResponse, ref int posHumanverify)
        {
            var posHumanVerifyName = strResponse.IndexOf("name=\"humanverify[input]\"");
            var startDeleimter = -1;
            var endDeleimter = -1;

            for (int i = posHumanVerifyName; i > 0; i--)
            {
                if (strResponse[i] == '<')
                {
                    startDeleimter = i;
                    posHumanverify = startDeleimter;

                    for (int j = startDeleimter; j < strResponse.Length; j++)
                    {
                        if (strResponse[j] == '>')
                        {
                            endDeleimter = j;
                            break;
                        }
                    }

                    break;
                }
            }

            var subHumanverify = strResponse.Substring(startDeleimter, endDeleimter - startDeleimter);
            var posIDHumanverify = subHumanverify.IndexOf("id");
            var startID = -1;
            var endID = -1;

            for (int i = posIDHumanverify; i < subHumanverify.Length; i++)
            {
                if (subHumanverify[i] == '"')
                {
                    startID = i;

                    for (int j = startID + 1; j < subHumanverify.Length; j++)
                    {
                        if (subHumanverify[j] == '"')
                        {
                            endID = j;
                            break;
                        }
                    }

                    break;
                }
            }
            
            return subHumanverify.Substring(startID + 1, endID - startID - 1);
        }

        public string RetrieveBlockrowCauHoi(string strResponse, string idHumanverify, int posInput)
        {
            var poshumanverify = strResponse.IndexOf("<label for=\"" + idHumanverify + "\">");
            var subStr = strResponse.Substring(poshumanverify, posInput - poshumanverify);
            var startDelemiter = subStr.IndexOf("<");
            while (startDelemiter != -1)
            {
                var endDelemiter = subStr.IndexOf(">", startDelemiter);
                var strReplace = subStr.Substring(startDelemiter, endDelemiter - startDelemiter + 1);
                subStr = subStr.Replace(strReplace, string.Empty);
                startDelemiter = subStr.IndexOf("<");
            }
            subStr = subStr.Replace("Câu hỏi ngẫu nhiên:", string.Empty);
            subStr = subStr.Replace("\r", string.Empty);
            subStr = subStr.Replace("\t", string.Empty);
            subStr = subStr.Replace("\n", string.Empty);

            return subStr;
        }

        public string RetrieveURLImageCapcha(string strResponse, string idHumanverify, int posInput)
        {
            var poshumanverify = strResponse.IndexOf("<label for=\"" + idHumanverify + "\">");
            var subStr = strResponse.Substring(poshumanverify, posInput - poshumanverify);
            var startImg = subStr.ToLower().IndexOf("<img");
            var endImg = -1;
            var strImg = string.Empty;
            var srcImg = string.Empty;

            for (int i = startImg + 1; i < subStr.Length; i++)
            {
                if (subStr[i] == '>')
                {
                    endImg = i;
                    strImg = subStr.Substring(startImg, endImg - startImg);
                    if (strImg.ToLower().Contains("hiddem"))
                    {
                        startImg = subStr.ToLower().IndexOf("<img", endImg + 1);
                        i = startImg;
                    }
                    else
                    {
                        var posSrc = strImg.ToLower().IndexOf("src");
                        var startSrc = -1;
                        var endSrc = -1;

                        for (int j = posSrc; j < strImg.Length; j++)
                        {
                            if (strImg[j] == '"')
                            {
                                startSrc = j;

                                for (int k = startSrc + 1; k < strImg.Length; k++)
                                {
                                    if (strImg[k] == '"')
                                    {
                                        endSrc = k;
                                        break;
                                    }
                                }

                                break;
                            }
                        }

                        srcImg = strImg.Substring(startSrc + 1, endSrc - startSrc - 1);
                        break;
                    }
                }
            }

            return srcImg;
        }

        public EnumVerifyMode RetrieveVerifyMode(string strResponse, string idHumanverify, int posHumanverify)
        {
            var posLabelFor = strResponse.IndexOf("<label for=\"" + idHumanverify + "\">");
            var subStr = strResponse.Substring(posLabelFor, posHumanverify - posLabelFor);
            if (subStr.ToLower().Contains("<img"))
            {
                return EnumVerifyMode.IMAGE;
            }
            return EnumVerifyMode.QUESTION;
        }

        private void InsertXacNhanBangCauHoi(object poster, string idHumanverify, int posInput)
        {
            object[] values = new object[6];
            values[0] = this.dtgvXacNhanBangCauHoi.Rows.Count + 1;
            values[1] = poster;
            values[2] = RetrieveBlockrowCauHoi(((Poster)poster).StrRespond, idHumanverify, posInput);

            dtgvXacNhanBangCauHoi.Rows.Add(values);
        }

        private void InsertXacNhanBangHinhAnh(object poster)
        {
            object[] values = new object[6];
            values[0] = this.dtgvXacNhanBangHinhAnh.Rows.Count + 1;
            values[1] = poster;
            values[2] = ((Poster)poster).Url;
            //Image img = DownloadImage(((Poster)poster).StrRespond);

            GlobalVariables.DictHtmls.Add(((Poster)poster).Url.Trim(), ((Poster)poster).StrRespond);

            dtgvXacNhanBangHinhAnh.Rows.Add(values);
        }

        public Image DownloadImage(string strResponse)
        {
            Image _tmpImage = null;

            try
            {
                var wb = new WebBrowser();
                wb.ScriptErrorsSuppressed = true;
                wb.DocumentText = strResponse;
                while (wb.ReadyState != WebBrowserReadyState.Complete)
                {
                    Application.DoEvents();
                }

                wb.Document.InvokeScript("vB_AJAX_ImageReg");
                
                if (wb.ReadyState == WebBrowserReadyState.Complete)
                {
                    foreach (HtmlElement img in wb.Document.Images)
                    {
                        var isitcaptcha = img.OuterHtml.IndexOf("imagereg", 0);
                        if (isitcaptcha > 0)
                        {
                            var captchaimg = img.OuterHtml.ToString();
                            img.SetAttribute("name", "captcha");
                            string ss = img.GetAttribute("src");
                            string html = "<html><head></head><body><p><img src='";
                            html += ss;
                            html += "'></p></body></html>";

                            var webBrowser2 = new WebBrowser();
                            webBrowser2.Navigate(ss);
                            webBrowser2.DocumentText = html;
                            while (webBrowser2.ReadyState != WebBrowserReadyState.Complete)
                            {
                                Application.DoEvents();
                            }
      
                            IHTMLDocument2 doc = (mshtml.IHTMLDocument2)
                            webBrowser2.Document.DomDocument;
                            IHTMLSelectionObject sobj = doc.selection;
                            HTMLBody body = doc.body as mshtml.HTMLBody;
                            sobj.empty();
                            IHTMLControlRange range = body.createControlRange() as IHTMLControlRange;
                            IHTMLControlElement imgs = (mshtml.IHTMLControlElement)webBrowser2.Document.Images[0].DomElement;

                            range.add(imgs);
                            range.select();
                            range.execCommand("Copy", false, null);

                            Bitmap bimg = new Bitmap(Clipboard.GetImage());
                        }
                    }
                }
            }
            catch (Exception _Exception)
            {
                // Error
                Console.WriteLine("Exception caught in process: {0}", _Exception.ToString());
                return null;
            }

            return _tmpImage;
        }

        private void LoadData()
        {
            dtgvKetQuaDangTin.Rows.Clear();
            dtgvXacNhanBangCauHoi.Rows.Clear();
            dtgvXacNhanBangHinhAnh.Rows.Clear();

            foreach(Poster poster in LstPoster)
            {
                poster.IDM = IDM;
                poster.Subj = Subj;
                poster.Mess = Mess;
                object[] values = new object[5];
                values[0] = this.dtgvKetQuaDangTin.Rows.Count + 1;
                values[1] = poster;

                dtgvKetQuaDangTin.Rows.Add(values);
            }
        }

        public void ClearSelection()
        {
            dtgvKetQuaDangTin.ClearSelection();
        }

        private void FrmKetQuaDangTin_Load(object sender, EventArgs e)
        {
            
        }

        private void btnNgungDangTin_Click(object sender, EventArgs e)
        {
            if (btnNgungDangTin.Text == "Ngừng đăng tin")
            {
                btnNgungDangTin.Text = "Tiết tục đăng";
            }
            else
            {
                btnNgungDangTin.Text = "Ngừng đăng tin";
            }
        }

        private void dtgvKetQuaDangTin_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (((e.RowIndex >= 0) && (dtgvKetQuaDangTin.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)) && ((e.ColumnIndex == 1) || (e.ColumnIndex == 4)))
            {
                Process.Start(dtgvKetQuaDangTin.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
            }
        }

        private void dtgvXacNhanBangCauHoi_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0 && e.ColumnIndex == 4)
            {
                if (dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[3].Value == null)
                {
                    MessageBoxEx.Show("Vui lòng nhập xác nhận", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                else if (dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[3].Value.ToString() == string.Empty)
                {
                    MessageBoxEx.Show("Vui lòng nhập xác nhận", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                else
                {
                    GlobalVariables.PreLoading();

                    AnswerVerify = dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[3].Value.ToString();
                    Poster poster = (Poster)dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[1].Value;
                    poster.HumanVerification = dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[3].Value.ToString();
                    poster.ProgressChanged -= OnPosterProgressChanged;
                    poster.ProgressChanged -= OnRePostingProgressChanged_ByCaptcha;
                    poster.ProgressChanged += OnRePostingProgressChanged_ByCauHoi;
                    poster.ReStartPost(e.RowIndex);

                    GlobalVariables.PosLoading();
                }
            }
        }

        private void dtgvXacNhanBangCauHoi_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (((e.RowIndex >= 0) && (dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)) && ((e.ColumnIndex == 1) || (e.ColumnIndex == 6)))
            {
                Process.Start(dtgvXacNhanBangCauHoi.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
            }
        }

        private void dtgvXacNhanBangHinhAnh_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                // Xem noi dung captcha
                if (e.ColumnIndex == 2)
                {
                    if (dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[2].Value != null)
                    {
                        var html = GlobalVariables.DictHtmls[dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[2].Value.ToString()];
                        frm = new FrmXacNhanImageCaptcha(html);
                        frm.Show();
                    }
                }
                else if (e.ColumnIndex == 4)
                {
                    if (dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[3].Value == null)
                    {
                        MessageBoxEx.Show("Vui lòng nhập xác nhận", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    else if (dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[3].Value.ToString() == string.Empty)
                    {
                        MessageBoxEx.Show("Vui lòng nhập xác nhận", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    else
                    {
                        frm.Close();

                        GlobalVariables.PreLoading();

                        AnswerVerify = dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[3].Value.ToString();
                        Poster poster = (Poster)dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[1].Value;
                        poster.HumanVerification = dtgvXacNhanBangHinhAnh.Rows[e.RowIndex].Cells[3].Value.ToString();
                        poster.ProgressChanged -= OnPosterProgressChanged;
                        poster.ProgressChanged -= OnRePostingProgressChanged_ByCauHoi;
                        poster.ProgressChanged += OnRePostingProgressChanged_ByCaptcha;
                        poster.ReStartPost(e.RowIndex);

                        GlobalVariables.PosLoading();
                    }
                }
            }
        }
    }
}
